#!/bin/bash

# K8s集群网络配置脚本
# 自动配置所有节点的网络设置

set -e

# 配置文件路径
CONFIG_FILE="./k8s-config.conf"
LOG_FILE="/var/log/k8s-network.log"

# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# 日志函数
log() {
    local level=$1
    shift
    local message="$*"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    
    case $level in
        "INFO")
            echo -e "${BLUE}[INFO]${NC} $message" | tee -a $LOG_FILE
            ;;
        "SUCCESS")
            echo -e "${GREEN}[SUCCESS]${NC} $message" | tee -a $LOG_FILE
            ;;
        "WARNING")
            echo -e "${YELLOW}[WARNING]${NC} $message" | tee -a $LOG_FILE
            ;;
        "ERROR")
            echo -e "${RED}[ERROR]${NC} $message" | tee -a $LOG_FILE
            ;;
    esac
}

# 错误处理函数
error_exit() {
    log "ERROR" "$1"
    log "ERROR" "网络配置失败，请检查日志: $LOG_FILE"
    exit 1
}

# 检查配置文件
check_config() {
    if [ ! -f "$CONFIG_FILE" ]; then
        error_exit "配置文件不存在: $CONFIG_FILE"
    fi
    
    # 加载配置文件
    source "$CONFIG_FILE"
    
    log "SUCCESS" "配置文件加载成功"
    log "INFO" "Master节点: $MASTER_IP"
    log "INFO" "Worker1节点: $WORKER1_IP"
    log "INFO" "Worker2节点: $WORKER2_IP"
    log "INFO" "网关: $GATEWAY"
    log "INFO" "DNS服务器: $DNS_SERVERS"
}

# 检查root权限
check_root() {
    if [ "$EUID" -ne 0 ]; then
        error_exit "请使用root用户运行此脚本"
    fi
    log "SUCCESS" "权限检查通过"
}

# 获取网络接口
get_network_interface() {
    local interface=$(ip route | grep default | awk '{print $5}' | head -1)
    
    if [ -z "$interface" ]; then
        error_exit "无法确定网络接口"
    fi
    
    log "INFO" "网络接口: $interface"
    echo "$interface"
}

# 配置静态IP
configure_static_ip() {
    local interface=$1
    local ip=$2
    local gateway=$3
    local dns_servers=$4
    
    log "INFO" "配置静态IP: $ip"
    
    # 备份原始网络配置
    cp /etc/netplan/*.yaml /etc/netplan/*.yaml.backup 2>/dev/null || true
    
    # 计算子网掩码
    local netmask="255.255.255.0"  # 默认/24
    
    # 创建网络配置
    cat > /etc/netplan/01-k8s-network.yaml << EOF
network:
  version: 2
  renderer: networkd
  ethernets:
    $interface:
      dhcp4: false
      addresses:
        - $ip/24
      gateway4: $gateway
      nameservers:
        addresses: [$dns_servers]
        search: []
EOF
    
    # 应用配置
    netplan apply
    
    log "SUCCESS" "静态IP配置完成: $ip"
}

# 配置DHCP
configure_dhcp() {
    local interface=$1
    
    log "INFO" "配置DHCP"
    
    # 备份原始网络配置
    cp /etc/netplan/*.yaml /etc/netplan/*.yaml.backup 2>/dev/null || true
    
    # 创建DHCP配置
    cat > /etc/netplan/01-k8s-network.yaml << EOF
network:
  version: 2
  renderer: networkd
  ethernets:
    $interface:
      dhcp4: true
      dhcp6: false
EOF
    
    # 应用配置
    netplan apply
    
    log "SUCCESS" "DHCP配置完成"
}

# 配置防火墙
configure_firewall() {
    log "INFO" "配置防火墙..."
    
    if [ "$FIREWALL_ENABLED" = "false" ]; then
        # 禁用防火墙
        ufw --force disable
        log "SUCCESS" "防火墙已禁用"
    else
        # 启用防火墙
        ufw --force enable
        
        # 默认策略
        ufw default deny incoming
        ufw default allow outgoing
        
        # 允许SSH
        ufw allow ssh
        
        # 允许K8s端口
        ufw allow 6443/tcp comment 'Kubernetes API server'
        ufw allow 2379:2380/tcp comment 'etcd server client API'
        ufw allow 10250/tcp comment 'Kubelet API'
        ufw allow 10251/tcp comment 'kube-scheduler'
        ufw allow 10252/tcp comment 'kube-controller-manager'
        ufw allow 30000:32767/tcp comment 'NodePort Services'
        
        # 允许集群内部通信
        ufw allow from $MASTER_IP comment 'Master node'
        ufw allow from $WORKER1_IP comment 'Worker1 node'
        ufw allow from $WORKER2_IP comment 'Worker2 node'
        
        log "SUCCESS" "防火墙规则配置完成"
    fi
}

# 配置内核网络参数
configure_kernel_network() {
    log "INFO" "配置内核网络参数..."
    
    # 创建网络参数配置
    cat > /etc/sysctl.d/k8s-network.conf << EOF
# Kubernetes网络参数
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.ipv4.conf.all.forwarding = 1
net.ipv4.conf.default.forwarding = 1
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.default.forwarding = 1
net.ipv4.tcp_congestion_control = bbr
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 65536 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.core.netdev_max_backlog = 5000
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.tcp_moderate_rcvbuf = 1
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.core.rmem_default = 262144
net.core.wmem_default = 262144
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 65536 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq
EOF
    
    # 应用配置
    sysctl --system
    
    # 加载网络模块
    modprobe br_netfilter
    echo 'br_netfilter' > /etc/modules-load.d/k8s.conf
    
    # 加载overlay模块
    modprobe overlay
    echo 'overlay' >> /etc/modules-load.d/k8s.conf
    
    log "SUCCESS" "内核网络参数配置完成"
}

# 测试网络连通性
test_network_connectivity() {
    log "INFO" "测试网络连通性..."
    
    # 测试网关连通性
    if ping -c 3 $GATEWAY &>/dev/null; then
        log "SUCCESS" "✓ 网关连通正常: $GATEWAY"
    else
        log "WARNING" "✗ 网关连通失败: $GATEWAY"
    fi
    
    # 测试DNS解析
    if nslookup google.com &>/dev/null; then
        log "SUCCESS" "✓ DNS解析正常"
    else
        log "WARNING" "✗ DNS解析失败"
    fi
    
    # 测试集群节点连通性
    for ip in $MASTER_IP $WORKER1_IP $WORKER2_IP; do
        if ping -c 3 $ip &>/dev/null; then
            log "SUCCESS" "✓ 节点连通正常: $ip"
        else
            log "WARNING" "✗ 节点连通失败: $ip"
        fi
    done
    
    log "SUCCESS" "网络连通性测试完成"
}

# 配置时间同步
configure_ntp() {
    log "INFO" "配置时间同步..."
    
    # 安装chrony
    apt-get update
    apt-get install -y chrony
    
    # 配置chrony
    cat > /etc/chrony/chrony.conf << EOF
# K8s集群时间同步配置
pool ntp.ubuntu.com iburst maxsources 4
pool 0.ubuntu.pool.ntp.org iburst maxsources 1
pool 1.ubuntu.pool.ntp.org iburst maxsources 1
pool 2.ubuntu.pool.ntp.org iburst maxsources 2

# 允许集群内部时间同步
allow $MASTER_IP/24
allow $WORKER1_IP/24
allow $WORKER2_IP/24

# 本地时间源
local stratum 10

# 记录统计信息
logdir /var/log/chrony
log measurements statistics tracking
EOF
    
    # 启动chrony服务
    systemctl enable chrony
    systemctl restart chrony
    
    # 同步时间
    chrony sources -v
    chrony tracking
    
    log "SUCCESS" "时间同步配置完成"
}

# 生成网络配置报告
generate_report() {
    local report_file="/tmp/k8s-network-report-$(date +%Y%m%d-%H%M%S).txt"
    
    log "INFO" "生成网络配置报告: $report_file"
    
    {
        echo "K8s集群网络配置报告"
        echo "生成时间: $(date)"
        echo "当前主机: $(hostname)"
        echo "=========================================="
        echo ""
        
        echo "网络配置:"
        echo "Master节点: $MASTER_IP"
        echo "Worker1节点: $WORKER1_IP"
        echo "Worker2节点: $WORKER2_IP"
        echo "网关: $GATEWAY"
        echo "DNS服务器: $DNS_SERVERS"
        echo ""
        
        echo "当前网络接口:"
        ip addr show
        echo ""
        
        echo "路由表:"
        ip route show
        echo ""
        
        echo "防火墙状态:"
        ufw status verbose
        echo ""
        
        echo "网络连通性测试:"
        echo -n "网关 ($GATEWAY): "
        if ping -c 1 $GATEWAY &>/dev/null; then
            echo "✓ 连通"
        else
            echo "✗ 不通"
        fi
        
        for ip in $MASTER_IP $WORKER1_IP $WORKER2_IP; do
            echo -n "节点 ($ip): "
            if ping -c 1 $ip &>/dev/null; then
                echo "✓ 连通"
            else
                echo "✗ 不通"
            fi
        done
        echo ""
        
        echo "DNS解析测试:"
        echo -n "google.com: "
        if nslookup google.com &>/dev/null; then
            echo "✓ 正常"
        else
            echo "✗ 失败"
        fi
        echo ""
        
        echo "时间同步状态:"
        chrony sources -v
        echo ""
        
    } > $report_file
    
    log "SUCCESS" "网络配置报告已生成: $report_file"
}

# 显示使用说明
show_usage() {
    echo "K8s集群网络配置脚本"
    echo ""
    echo "用法:"
    echo "  $0 [选项]"
    echo ""
    echo "选项:"
    echo "  --node-type=TYPE     节点类型 (master|worker1|worker2)"
    echo "  --ip=IP              IP地址"
    echo "  --dhcp               使用DHCP"
    echo "  --test-only          仅测试网络连通性"
    echo "  --help               显示帮助信息"
    echo ""
    echo "示例:"
    echo "  $0 --node-type=master --ip=192.168.1.10"
    echo "  $0 --node-type=worker1 --ip=192.168.1.11"
    echo "  $0 --dhcp"
    echo "  $0 --test-only"
}

# 主函数
main() {
    log "INFO" "开始K8s集群网络配置..."
    log "INFO" "配置日志: $LOG_FILE"
    
    # 解析命令行参数
    local node_type=""
    local custom_ip=""
    local use_dhcp=false
    local test_only=false
    
    while [[ $# -gt 0 ]]; do
        case $1 in
            --node-type=*)
                node_type="${1#*=}"
                shift
                ;;
            --ip=*)
                custom_ip="${1#*=}"
                shift
                ;;
            --dhcp)
                use_dhcp=true
                shift
                ;;
            --test-only)
                test_only=true
                shift
                ;;
            --help)
                show_usage
                exit 0
                ;;
            *)
                echo "未知参数: $1"
                show_usage
                exit 1
                ;;
        esac
    done
    
    # 执行配置步骤
    check_root
    check_config
    
    if [ "$test_only" = true ]; then
        test_network_connectivity
        generate_report
        exit 0
    fi
    
    # 获取网络接口
    local interface=$(get_network_interface)
    
    # 配置网络
    if [ "$use_dhcp" = true ]; then
        configure_dhcp "$interface"
    else
        # 确定IP地址
        local ip=""
        case $node_type in
            "master")
                ip="$MASTER_IP"
                ;;
            "worker1")
                ip="$WORKER1_IP"
                ;;
            "worker2")
                ip="$WORKER2_IP"
                ;;
            *)
                if [ -n "$custom_ip" ]; then
                    ip="$custom_ip"
                else
                    error_exit "请指定节点类型或IP地址"
                fi
                ;;
        esac
        
        configure_static_ip "$interface" "$ip" "$GATEWAY" "$DNS_SERVERS"
    fi
    
    # 配置防火墙
    configure_firewall
    
    # 配置内核网络参数
    configure_kernel_network
    
    # 配置时间同步
    configure_ntp
    
    # 测试网络连通性
    test_network_connectivity
    
    # 生成报告
    generate_report
    
    log "SUCCESS" "K8s集群网络配置完成！"
    log "INFO" "请重启网络服务或重启服务器以确保配置生效"
}

# 运行主函数
main "$@"
